package itsm.isperp.framework.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.springframework.util.Assert;

/**
 * 反射器帮助
 * 
 * @author lizx
 * @date 2013-1-15
 * @version V1.0
 */
public final class ReflectHelper {

	/**
	 * 根据字段名取得指定实体的字段类
	 * 
	 * @param obj
	 *            指定实体
	 * @param fieldName
	 *            实体字段值
	 * @return 实体字段名的字段类
	 */
	public static Field getFieldByFieldName(Object obj, String fieldName) {
		for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass
				.getSuperclass()) {
			try {
				return superClass.getDeclaredField(fieldName);
			} catch (NoSuchFieldException e) {
			}
		}
		return null;
	}

	public static Field getFieldByFieldName(Class<?> clazz, String fieldName) {
		for (Class<?> superClass = clazz; superClass != Object.class; superClass = superClass
				.getSuperclass()) {
			try {
				return superClass.getDeclaredField(fieldName);
			} catch (NoSuchFieldException e) {
			}
		}
		return null;
	}

	/**
	 * 根据字段名取得此字段的值
	 * 
	 * @param obj
	 *            实体
	 * @param fieldName
	 *            字段名
	 * @return 字段值
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	public static Object getValueByFieldName(Object obj, String fieldName)
			throws SecurityException, NoSuchFieldException,
			IllegalArgumentException, IllegalAccessException {
		Field field = getFieldByFieldName(obj, fieldName);
		Object value = null;
		if (field != null) {
			if (field.isAccessible()) {
				value = field.get(obj);
			} else {
				field.setAccessible(true);
				value = field.get(obj);
				field.setAccessible(false);
			}
		}
		return value;
	}

	/**
	 * 设置一个字段的值
	 * 
	 * @param obj
	 *            实体类
	 * @param fieldName
	 *            字段名
	 * @param value
	 *            值
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	public static void setValueByFieldName(Object obj, String fieldName,
			Object value) throws SecurityException, NoSuchFieldException,
			IllegalArgumentException, IllegalAccessException {
		Field field = obj.getClass().getDeclaredField(fieldName);
		if (field.isAccessible()) {
			field.set(obj, value);
		} else {
			field.setAccessible(true);
			field.set(obj, value);
			field.setAccessible(false);
		}
	}

	/**
	 * 获取某个类的自由属性及其所有父类中继承的属性
	 * 
	 * @param aClazz
	 * @return
	 */
	public static final void getDeclaredFields(Class<?> clazz, List<Field> list) {
		Field[] declaredFields = clazz.getDeclaredFields();

		for (Field field : declaredFields) {
			list.add(field);
		}

		Class<?> superclass = clazz.getSuperclass();
		if (superclass != null) {// 简单的递归一下
			getDeclaredFields(superclass, list);
		}
	}

	/**
	 * 将实体转化为字符串
	 * 
	 * @param entity
	 *            实体
	 * @return 字符串
	 */
	public static final String toString(Object entity) {
		return ReflectionToStringBuilder.toString(entity);
	}

	/**
	 * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. 如向上转型到Object仍无法找到, 返回null.
	 * <p/>
	 * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object...
	 * args)
	 */
	public static Method getAccessibleMethod(final Object obj,
			final String methodName, final Class<?>... parameterTypes) {
		Assert.notNull(obj, "object can't be null");
		for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass
				.getSuperclass()) {
			try {
				Method method = superClass.getDeclaredMethod(methodName,
						parameterTypes);

				method.setAccessible(true);

				return method;

			} catch (NoSuchMethodException e) {// NOSONAR
				// Method不在当前类定义,继续向上转型
			}
		}
		return null;
	}
}
